package cn.ligoo.util;

public class ByteUtils {
	/**
	 * 
	 * Convert byte[] to hex string.这里我们可以将byte转换成int，然后利用Integer.toHexString(byte)来转换成16进制字符串。
	 * 
	 * @param src
	 *            byte[] data
	 * @param separator
	 *            separator
	 * @return hex string
	 */

	public static String bytesToHexString(byte[] src, String separator) {

		StringBuilder stringBuilder = new StringBuilder("");
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
			if (null != separator) {
				stringBuilder.append(separator);
			}
		}
		return stringBuilder.toString();
	}

	/**
	 * @param src
	 * @return
	 */
	public static String bytesToHexString(byte[] src) {
		return ByteUtils.bytesToHexString(src, null);
	}

	/**
	 * Convert hex string to byte[]
	 * 
	 * @param hexString
	 *            the hex string
	 * @return byte[]
	 */
	private static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	/**
	 * Convert char to byte
	 * 
	 * @param c
	 *            char
	 * @return byte
	 */

	public static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	/**
	 * int to bytes 产生的数据在高
	 */
	private static byte[] intToByte(int i) {
		byte[] bt = new byte[4];
		bt[0] = (byte) (0xff & i);
		bt[1] = (byte) ((0xff00 & i) >> 8);
		bt[2] = (byte) ((0xff0000 & i) >> 16);
		bt[3] = (byte) ((0xff000000 & i) >> 24);
		return bt;
	}

	/**
	 * bytes to int 产生的int数据在高位
	 */
	private static int bytesToInt(byte[] bytes) {
		int num = bytes[0] & 0xFF;
		num |= ((bytes[1] << 8) & 0xFF00);
		num |= ((bytes[2] << 16) & 0xFF0000);
		num |= ((bytes[3] << 24) & 0xFF000000);
		return num;
	}

	private static int byteToUnsignedInt(byte b) {
		return (b & 0xff);
	}

	private static int bytesToUnsignedInt(byte[] bytes, int offset) {
		return (bytes[offset] & 0xFF);
	}

	/**
	 * Convert an int to a byte array
	 * 
	 * @param value
	 *            int
	 * @return byte[]
	 */

	private static byte[] intToByteArray(int value) {
		byte[] b = new byte[4];
		for (int i = 0; i < 4; i++) {
			int offset = (b.length - 1 - i) * 8;
			b[i] = (byte) ((value >>> offset) & 0xFF);
		}
		return b;
	}

	/**
	 * Convert the byte array to an int starting from the given offset.
	 * 
	 * @param b
	 *            The byte array
	 * @param offset
	 *            The array offset,如果byte数组长度就是4，则该值为0
	 * @return The integer
	 */
	private static int byteArrayToInt(byte[] b, int offset) {
		int value = 0;
		for (int i = 0; i < 4; i++) {
			int shift = (4 - 1 - i) * 8;
			value += (b[i + offset] & 0x000000FF) << shift;
		}
		return value;
	}

	private static int bytes2ToInt(byte[] bytes) {
		int fromByte = 0;
		for (int i = 0; i < 2; i++) {
			int n = (bytes[i] < 0 ? bytes[i] + 256 : (int) bytes[i]) << (8 * i);
			// System.out.println(n);
			fromByte += n;
		}
		return fromByte;
	}

	/**
	 * 
	 * Transfer a number which is a byte represented by a integer number to a 8 bits string.
	 * 
	 * For Example 8->00001000, -3->10000101
	 * 
	 * @param b
	 * 
	 * @return
	 */
	public static String getEightBitsStringFromByte(int b) {
		// if this is a positive number its bits number will be less than 8
		// so we have to fill it to be a 8 digit binary string
		// b=b+100000000(2^8=256) then only get the lower 8 digit
		b |= 256; // mark the 9th digit as 1 to make sure the string has at least 8 digits
		String str = Integer.toBinaryString(b);
		int len = str.length();
		return str.substring(len - 8, len);
	}

	/**
	 * 
	 * Transfer a 8 bits 0/1 string to byte
	 * 
	 * @param str
	 * 
	 * @return
	 * 
	 * @throws Exception
	 *             Not a available 8 digits long 0/1 sting
	 */
	public static byte getByteFromEightBitsString(String str) throws Exception {
		if (str.length() != 8) {
			throw new Exception("It''s not a 8 length string");
		}
		byte b;

		// check if it''s a minus number
		if (str.substring(0, 1).equals("1")) {
			// get lower 7 digits original code
			str = "0" + str.substring(1);
			b = Byte.valueOf(str, 2);
			// then recover the 8th digit as 1 equal to plus 1000000
			b |= 128;
		} else {
			b = Byte.valueOf(str, 2);
		}
		return b;
	}
}
